﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Configuration;
using System.Data;
using System.Xml.Schema;
using System.IO;

namespace XmlDataComminucation
{
    public abstract class GeneralFunctions
    {
        private static readonly string NamespaceUrl = "http://picking.com.cn";
        private static void ShowCompileError(object sender, ValidationEventArgs e)
        {

        }

        public static DataTable GetDataTableByXmlNodes(XmlNodeList nodes)
        {
            if (nodes.Count == 0) return new DataTable();
            DataTable dt = CreateDataTableSchema(nodes[0]);
            foreach (XmlNode item in nodes)
            {
                DataRow row = dt.NewRow();
                foreach (XmlNode childNode in item.ChildNodes)
                {
                    row[childNode.Name] = childNode.InnerText;
                }
                dt.Rows.Add(row);
            }

            return dt;
        }

        public static DataRow GetDataRowByXmlNode(XmlNode node)
        {
            if (node == null) return null;
            DataTable dt = CreateDataTableSchema(node);
            DataRow row = dt.NewRow();
            foreach (XmlNode item in node.ChildNodes)
            {
                row[item.Name] = item.InnerText;
            }
            dt.Rows.Add(row);
            return dt.Rows[0];
        }

        public static DataTable CreateDataTableSchema(XmlNode node)
        {
            DataTable dt = new DataTable();
            if (node == null) return dt;
            foreach (XmlNode item in node.ChildNodes)
            {
                dt.Columns.Add(new DataColumn(item.Name, typeof(string)));
            }
            dt.TableName = node.ParentNode.Name;
            return dt;
        }

        public static XmlDocument GetXmlDocument(string lineCode)
        {
            XmlDocument doc = new XmlDocument();
            if (string.Equals("Line1", lineCode))
            {                
                string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath1"];
                doc.Load(filePath);
            }

            if (string.Equals("Line2", lineCode))
            {
                string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath2"];
                doc.Load(filePath);
            }

            if (string.Equals("Line3", lineCode))
            {
                string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath3"];
                doc.Load(filePath);
            }
            return doc;
        }

        public static void SaveXmlDocument(XmlDocument doc, string lineCode)
        {
            if (string.Equals("Line1", lineCode))
            {
                string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath1"];
                doc.Save(filePath);
            }

            if (string.Equals("Line2", lineCode))
            {
                string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath2"];
                doc.Save(filePath);
            }

            if (string.Equals("Line3", lineCode))
            {
                string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath3"];
                doc.Save(filePath);
            }
        }

        public static XmlDocument GetFileDocument()
        {
            XmlDocument doc = new XmlDocument();

            string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath"];
            doc.Load(filePath);

            return doc;
        }

        public static String GetFileName()
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath1"];

            filePath = filePath + "|" + AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath2"];

            //string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath3"];

            return filePath;
        }


        public static void SaveFileDocument(XmlDocument doc)
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["DataFilePath"];
            doc.Save(filePath);
        }

        public static XmlNode CreateRecordInTable(XmlDocument doc, string tableName, List<string> columnNames)
        {
            XmlNamespaceManager nsmgr = GeneralFunctions.GetXmlNamespaceMgr();
            XmlNode node = doc.SelectSingleNode("//x:" + tableName, nsmgr);
            XmlNode recordNode = doc.CreateElement(string.Empty, "Record", NamespaceUrl);
            node.AppendChild(recordNode);
            foreach (var item in columnNames)
            {
                XmlNode columnNode = doc.CreateElement(string.Empty, item, NamespaceUrl);
                recordNode.AppendChild(columnNode);
            }
            return recordNode;
        }

        public static XmlNode CreateRecordInTable(XmlDocument doc, string tableName, Dictionary<string, string> columnNamesAndValues)
        {
            XmlNamespaceManager nsmgr = GeneralFunctions.GetXmlNamespaceMgr();
            XmlNode node = doc.SelectSingleNode("//x:" + tableName, nsmgr);

            if (node == null)
            {
                if (!doc.HasChildNodes)
                {
                    XmlNode nodeRoot = doc.CreateElement(string.Empty, "Tables", NamespaceUrl);

                    doc.ImportNode(nodeRoot, false);
                }

                node = doc.CreateElement(string.Empty, tableName, NamespaceUrl);
                doc.ChildNodes[1].AppendChild(node);
            }

            XmlNode recordNode = doc.CreateElement(string.Empty, "Record", NamespaceUrl);
            node.AppendChild(recordNode);
            foreach (var item in columnNamesAndValues.Keys)
            {
                XmlNode columnNode = doc.CreateElement(string.Empty, item, NamespaceUrl);
                columnNode.InnerText = columnNamesAndValues[item];
                recordNode.AppendChild(columnNode);
            }
            return recordNode;
        }

        public static XmlNode RemoveAllRecordsInTable(XmlDocument doc, string tableName)
        {
            XmlNamespaceManager nsmgr = GeneralFunctions.GetXmlNamespaceMgr();
            XmlNode node = doc.SelectSingleNode("//x:" + tableName, nsmgr);

            if (node != null)
            {
                node.RemoveAll();
            }

            return node;
        }

        public static XmlNamespaceManager GetXmlNamespaceMgr()
        {
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(new XmlDocument().NameTable);
            nsmgr.AddNamespace("x", NamespaceUrl);
            return nsmgr;
        }

        public static DataTable CreateDataTableFromXmlSchema(string tableName)
        {
            DataTable dt = new DataTable();
            string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["SchemaFilePath"];
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            XmlSchema schema = XmlSchema.Read(fs, new ValidationEventHandler(ShowCompileError));
            schema.Compile(new ValidationEventHandler(ShowCompileError));

            XmlSchemaComplexType complexType;
            foreach (XmlSchemaType type in schema.SchemaTypes.Values)
            {
                complexType = type as XmlSchemaComplexType;
                if (complexType != null)
                {
                    if (!complexType.Name.Contains(tableName)) continue;
                    TraverseParticle(complexType.ContentTypeParticle, dt);
                }
            }
            dt.TableName = tableName;
            return dt;
        }

        private static void TraverseParticle(XmlSchemaParticle particle, DataTable dt)
        {
            if (particle is XmlSchemaElement)
            {
                XmlSchemaElement elem = particle as XmlSchemaElement;

                if (elem.RefName.IsEmpty)
                {
                    XmlSchemaType type = (XmlSchemaType)elem.ElementSchemaType;
                    XmlSchemaComplexType complexType = type as XmlSchemaComplexType;
                    if (complexType != null && complexType.Name == null)
                        TraverseParticle(complexType.ContentTypeParticle, dt);
                    else
                    {
                        dt.Columns.Add(new DataColumn(elem.Name, typeof(string)));//type->elem.ElementSchemaType,we use string currently
                    }
                }
            }
            else if (particle is XmlSchemaGroupBase)
            { //xs:all, xs:choice, xs:sequence
                XmlSchemaGroupBase baseParticle = particle as XmlSchemaGroupBase;
                foreach (XmlSchemaParticle subParticle in baseParticle.Items)
                    TraverseParticle(subParticle, dt);
            }
        }
    }
}
